<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      function request(i) {
        return () => {
          return new Promise((resolve, reject) => {
            setTimeout(() => {
              resolve(i);
            }, 2000);
          });
        };
      }

      class TaskQueue {
        //构造任务队列
        constructor() {
          this.taskArr = [];
          //最大任务数量
          this.max = 5;
        }
        addTask(task) {
          this.taskArr.push(task);
          console.log(this.taskArr);
        }
        //处理函数
        run() {
          //判断最大任务数量
          let length = this.taskArr.length;
          //判断任务队列里还有没有任务 没有就返回
          if (!length > 0) {
            return;
          }
          //设置最小值,用来循环
          let min = Math.min(this.max, length);
          //循环数组处理任务
          for (let i = 0; i < min; i++) {
            this.max--;
            // console.log(this.taskArr);
            const temp = this.taskArr.shift();
            //利用异步任务特点,每五次生成五个计时器,计时器又是同时计时,达到每次处理五次任务的效果
            temp()
              .then((value) => {
                console.log(value);
              })
              .catch((reson) => {
                console.log(reson);
              })
              .finally(() => {
                this.max++;
                this.run();
              });
          }
        }
      }

      const taskQueue = new TaskQueue();

      for (let index = 1; index <= 20; index++) {
        const task = request(index);
        taskQueue.addTask(task);
      }
      taskQueue.run();
    </script>
  </body>
</html>
